﻿using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.Domain.Repositories;
using YAKEJI.Abp.Domain.Repositories;
using YAKEJI.Xaf.Numbers;
using YAPACS.Organizations;

namespace YAPACS.RisServer.Controllers;
[Authorize]
public class SettingsController : AbpControllerBase
{
    private readonly IRepository<ApplicationUser, Guid> _userRepository;
    private readonly IRepository<Setting, Guid> _settingRepository;
    private readonly IRepository<UserGroup, Guid> _groupRepository;
    private readonly INumberService _numberService;
    private readonly ICurrentUserOrganization _currentUserOrganization;

    public SettingsController(
        IRepository<ApplicationUser, Guid> userRepository,
        IRepository<Setting, Guid> settingRepository,
        IRepository<UserGroup, Guid> groupRepository,
        INumberService numberService,
        ICurrentUserOrganization currentUserOrganization)
    {
        _userRepository = userRepository;
        _settingRepository = settingRepository;
        _groupRepository = groupRepository;
        _numberService = numberService;
        _currentUserOrganization = currentUserOrganization;
    }

    private async Task<Setting> CreateNewSetting(string name, string value)
    {
        var setting = await _settingRepository.NewEntityAsync();

        setting.Name = name;
        setting.Value = value;
        setting.Code = await _numberService.GetNumberAsync(new NumberOptions
        {
            NumberId = typeof(Setting).FullName,
            NumberTemplate = "S{0:<INDEX>,00000}",
        }, setting);

        return setting;
    }

    [HttpGet("/api/get-settings")]
    public async Task<IActionResult> GetSettings()
    {
        var user = await _userRepository.GetAsync(_currentUserOrganization.UserId);
        return Ok(user.GetUserSettings().Select(s => new
        {
            s.Name,
            s.Value
        }));
    }

    [HttpGet("/api/get-setting")]
    public async Task<IActionResult> GetSetting([FromQuery] string name)
    {
        var user = await _userRepository.GetAsync(_currentUserOrganization.UserId);
        return Ok(user.GetUserSettings().Where(s => s.Name == name).Select(s => s.Value).FirstOrDefault());
    }

    [HttpPost("/api/set-setting")]
    public async Task<IActionResult> SetSetting(string name, string value, string type)
    {
        var user = await _userRepository.GetAsync(_currentUserOrganization.UserId);

        switch (type?.ToLowerInvariant())
        {
            case "usergroup":
                {
                    var userGroup = await _groupRepository.FirstOrDefaultAsync(g => g.Id == _currentUserOrganization.DepartmentId);
                    if (userGroup != null)
                    {
                        var setting = userGroup.Settings.FirstOrDefault(user => user.Name == name);
                        if (setting == null)
                        {
                            user.Settings.Add(await CreateNewSetting(name, value));
                        }
                        else
                        {
                            setting.Value = value;
                        }
                    }
                }
                break;
            case "department":
                {
                    var userGroup = await _groupRepository.FirstOrDefaultAsync(g => g.Id == _currentUserOrganization.DepartmentId);
                    if (userGroup != null)
                    {
                        var setting = userGroup.Department.Settings.FirstOrDefault(user => user.Name == name);
                        if (setting == null)
                        {
                            user.Settings.Add(await CreateNewSetting(name, value));
                        }
                        else
                        {
                            setting.Value = value;
                        }
                    }
                }
                break;
            default:
                {
                    var setting = user.Settings.FirstOrDefault(user => user.Name == name);
                    if (setting == null)
                    {
                        user.Settings.Add(await CreateNewSetting(name, value));
                    }
                    else
                    {
                        setting.Value = value;
                    }
                }
                break;
        }

        return Ok();
    }
}
